package im.composer.audio.outputstream.flac;

import java.io.IOException;

import javax.sound.sampled.AudioFormat;

import org.tritonus.dsp.interfaces.FloatSampleWriter;
import org.tritonus.share.sampled.FloatSampleBuffer;
import org.tritonus.share.sampled.file.TDataOutputStream;

import im.composer.audio.outputstream.AbstractAudioOutputStream;
import net.sourceforge.javaflacencoder.FLACEncoder;
import net.sourceforge.javaflacencoder.StreamConfiguration;

public class FLACAudioOutputStream extends AbstractAudioOutputStream implements FloatSampleWriter {
	private static final float _____ratio = 2 << 22;
	private final FLACEncoder encoder = new FLACEncoder();
	private boolean open = false;

	public FLACAudioOutputStream(TDataOutputStream dataOutputStream, long length, AudioFormat format,int min_block_size,int max_block_size) {
		super(dataOutputStream, format, length);
		encoder.setOutputStream(new TFLACOutputStream(dataOutputStream));
		int a = format.getSampleSizeInBits();
		if (a > 24) {
			a = 24;
		}
		StreamConfiguration conf = new StreamConfiguration(getFormat().getChannels(), min_block_size,max_block_size, (int) format.getSampleRate(), a);
		encoder.setStreamConfiguration(conf);
	}

	@Override
	public void write(FloatSampleBuffer buffer) throws IOException {
		write(buffer, 0, buffer.getSampleCount());
	}

	@Override
	public void write(FloatSampleBuffer fsb, int offset, int sampleCount) throws IOException {
		if (!open) {
			encoder.openFLACStream();
			open = true;
		}
		int[] arr = new int[fsb.getChannelCount() * sampleCount];
		int k = 0;
		for (int i = offset; i < sampleCount; i++) {
			for (int j = 0; j < fsb.getChannelCount(); j++) {
				float sample = fsb.getChannel(j)[i];
				int _sample = (int) (sample * _____ratio);
				arr[k] = _sample;
				k++;
			}
		}
		encoder.addSamples(arr, sampleCount);
		encoder.encodeSamples(encoder.fullBlockSamplesAvailableToEncode(), false);
	}

	@Override
	public int write(byte[] abData, int nOffset, int nLength) throws IOException {
		FloatSampleBuffer fsb = new FloatSampleBuffer(abData, nOffset, nLength, getFormat());
		write(fsb);
		return nLength;
	}

	@Override
	public void close() throws IOException {
		try {
			encoder.encodeSamples(encoder.fullBlockSamplesAvailableToEncode(), true);
		} catch (Exception e) {
		}
		try {
			encoder.encodeSamples(encoder.samplesAvailableToEncode(), true);
		} catch (Exception e) {
		}
		open = false;
		super.close();
	}

}